home *** CD-ROM | disk | FTP | other *** search
/ Scene 96 / Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso / misc / coding / pump_src / setup / libfile.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-10-26  |  9.3 KB  |  426 lines

  1. UNIT LibFile;
  2.  
  3. INTERFACE
  4.  
  5. USES Dos,Objects;
  6.  
  7. TYPE
  8.   PLFDirEntry = ^TLFDirEntry;
  9.   TLFDirEntry =
  10.     RECORD
  11.       name : ARRAY[1..24] OF CHAR;
  12.       offs : LONGINT;
  13.       size : LONGINT;
  14.     END;
  15.  
  16. VAR
  17.    FicheroExe : STRING;
  18.    header: ARRAY [1..28] OF BYTE;
  19.    handle,PSPSegment,StartSegment:WORD;
  20.    item: ARRAY [1..2] OF WORD;
  21.    memory,imagesize:WORD;
  22.    commandline:STRING[125];
  23.  
  24. FUNCTION  LF_FindFile(FName: STRING) : PLFDirEntry;
  25. PROCEDURE LF_Free;
  26. PROCEDURE ExecFile(pos:LONGINT);
  27.  
  28. IMPLEMENTATION
  29.  
  30.  
  31. PROCEDURE LF_Init(FName: STRING; VAR Coll: TCollection);
  32.   VAR
  33.     St         : TDosStream;
  34.     n, NFiles,
  35.     LastOffset : LONGINT;
  36.     i          : INTEGER;
  37.     de         : PLFDirEntry;
  38.   LABEL
  39.     Fin;
  40.   BEGIN
  41.     St.Init(Fname, stOpenRead);
  42.     IF St.Status <> stOk THEN EXIT;
  43.  
  44.     St.Seek(St.GetSize-16);
  45.     St.Read(n, 4);
  46.     IF n <> $DF73B489 THEN GOTO Fin;
  47.     St.Read(NFiles, 4);
  48.     St.Read(n, 4);
  49.     St.Read(LastOffset, 4);
  50.  
  51.     LastOffset := St.GetSize-LastOffset;
  52.     St.Seek(LastOffset);
  53.  
  54.     FOR i := 1 TO NFiles DO
  55.       BEGIN
  56.         NEW(de);
  57.         St.Read(de^, SIZEOF(de^));
  58.         de^.offs := LastOffset - de^.offs;
  59.         Coll.Insert(de);
  60.       END;
  61.  
  62. Fin:
  63.     St.Done;
  64.   END;
  65.  
  66. VAR
  67.   LF_Coll : TCollection;
  68.  
  69. FUNCTION CmpName(VAR _p1; p2: STRING) : BOOLEAN;
  70.   VAR
  71.     p1 : ARRAY[1..24] OF CHAR ABSOLUTE _p1;
  72.     i  : INTEGER;
  73.   BEGIN
  74.     CmpName := FALSE;
  75.     FOR i := 1 TO Length(p2) DO
  76.       IF p1[i] <> p2[i] THEN EXIT;
  77.     CmpName := TRUE;
  78.   END;
  79.  
  80. FUNCTION LF_FindFile(FName: STRING) : PLFDirEntry;
  81.   VAR
  82.     i  : INTEGER;
  83.     de : PLFDirEntry;
  84.   BEGIN
  85.     LF_FindFile := NIL;
  86.     FOR i := 1 TO Length(FName) DO
  87.       FName[i] := UpCase(FName[i]);
  88.     FOR i := 0 TO LF_Coll.Count - 1 DO
  89.       BEGIN
  90.         de := LF_Coll.At(i);
  91.         IF CmpName(de^.name, FName) THEN
  92.           BEGIN
  93.             LF_FindFile := de;
  94.             EXIT;
  95.           END;
  96.       END;
  97.   END;
  98.  
  99. PROCEDURE LF_Free;
  100.   VAR
  101.     i  : INTEGER;
  102.     de : PLFDirEntry;
  103.   BEGIN
  104.     FOR i := LF_Coll.Count - 1 DOWNTO 0 DO
  105.       BEGIN
  106.         de := LF_Coll.At(i);
  107.         Dispose(de);
  108.       END;
  109.     LF_Coll.DeleteAll;
  110.     LF_Coll.Done;
  111.   END;
  112.  
  113. {                                                           }
  114. { convierte un string en formato ASCIIZ para utilizarlo con }
  115. { las funciones del DOS                                     }
  116. {                                                           }
  117.  
  118. PROCEDURE StringToAsciiz; ASSEMBLER;
  119. ASM
  120.    mov bx,OFFSET FicheroExe
  121.    xor cx,cx
  122.    mov cl,[bx]
  123. @@StringToASCII:
  124.    mov al,[bx+1]
  125.    mov [bx],al
  126.    inc bx
  127.    loop @@StringToASCII
  128.    mov byte ptr [bx],0
  129. END;
  130.  
  131. {                                                           }
  132. { Carga, reubica y ejecuta un fichero .EXE                  }
  133. { Versión 2.11                                              }
  134. {                                                           }
  135.  
  136. PROCEDURE ExecFile(pos:LONGINT); ASSEMBLER;
  137. ASM
  138.    push es
  139.    call StringToAsciiz          { convierte el nombre del .exe a ASCIIZ }
  140.  
  141.    {------------------}
  142.  
  143.    push ds
  144.    mov ax,3d00h
  145.    mov dx,OFFSET FicheroExe
  146.    int 21h                      { abre el fichero para sólo lectura }
  147.  
  148.    { indexado del fichero }
  149.  
  150.    push ax
  151.    mov bx,ax       { handle del fichero }
  152.    mov ax,04200h
  153.    mov dx,word ptr [pos]
  154.    mov cx,word ptr [pos+2]
  155.    int 21h
  156.    pop ax
  157.  
  158.    mov [handle],ax              { guarda el handle del fichero }
  159.    mov bx,[handle]
  160.    mov dx,OFFSET header         { cabecera del fichero .exe }
  161.    mov cx,28
  162.    mov ah,3fh
  163.    int 21h                      { lee los 28 bytes estándar de la cabecera }
  164.    pop ds
  165.  
  166.    {-------------------}
  167.  
  168.    mov bx,OFFSET header
  169.    mov cx,[bx+08h]              { longitud del header en parágrafos }
  170.    mov ax,16
  171.    imul cx                      { DX:AX -> posición de inicio de módulo }
  172.    mov cx,dx
  173.    mov dx,ax                    { CX:DX -> posición para el LSEEK }
  174.    add dx,word ptr [pos]
  175.    adc cx,word ptr [pos+2]
  176.    mov bx,[handle]
  177.    xor al,al
  178.    mov ah,42h
  179.    int 21h                      { posiciona el puntero del fichero al }
  180.                                 { inicio del modulo del programa      }
  181.  
  182.    {--------------------}
  183.  
  184.    mov bx,OFFSET header
  185.    mov ax,[bx+4]                { longitud total incluyendo la cabecera }
  186.    inc ax                       { 1+ por si acaso }
  187.    mov cx,32
  188.    mul cx                       { parágrafos totales }
  189.    mov [imagesize],ax           { tamaño del modulo del programa }
  190.  
  191.    {--------------------}
  192.  
  193.    { Calcula los nuevos parámetros mínimo y máximo para ejecutar el programa }
  194.    mov ax,[imagesize]
  195.    add ax,16      { Para el PSP }
  196.    cmp ax,WORD PTR header[0Ah]
  197.    jbe @@MinOk
  198.    mov WORD PTR header[0Ah],ax
  199. @@MinOk:
  200.    cmp ax,WORD PTR header[0Ch]
  201.    jbe @@MaxOk
  202.    mov WORD PTR header[0Ch],ax
  203. @@MaxOk:
  204.  
  205.    {--------------------}
  206.  
  207.    mov bx,WORD PTR header[0Ch]
  208.    mov [memory],bx
  209.    mov ah,48h
  210.    int 21h
  211.    jnc @@no_error0
  212.    cmp bx,WORD PTR header[0Ah]
  213.    jb  @@NoHayMem
  214.    mov [memory],bx
  215.    mov ah,48h
  216.    int 21h                      { con esto reservamos el máximo de memoria }
  217. @@no_error0:
  218.    mov [PSPSegment],ax
  219.  
  220.    { genera un nuevo PSP...UNDOCUMENTED! }
  221.  
  222.    push ax
  223.    mov dx,ax
  224.    mov ah,055h
  225.    mov si,dx
  226.    add si,10h
  227.    add si,[memory]              { valor a escribir en el campo de memoria }
  228.    int 21h                      { del PSP                                 }
  229.    pop ax
  230.  
  231.    mov es,ax
  232.    xor di,di
  233.    mov word ptr es:[di+0ah],OFFSET @@retorna
  234.    mov es:[di+0ch],cs
  235.  
  236.    add ax,16
  237.    mov [StartSegment],ax
  238.  
  239.    {----------------------}
  240.  
  241.    { aquí nos encargamos de leer el módulo principal del programa, que }
  242.    { no es más que el código y los datos en sí...                      }
  243.  
  244.    mov bx,[handle]
  245.    mov cx,[imagesize]
  246.    push ds
  247.    mov ds,[StartSegment]
  248. @@next_block:
  249.    push cx
  250.    xor dx,dx
  251.    mov cx,16                   { 16 bytes cada bloque }
  252.    mov ah,3fh
  253.    xor al,al
  254.    int 21h
  255.    jc @@end_read
  256.    mov ax,ds
  257.    inc ax
  258.    mov ds,ax
  259.    pop cx
  260.    loop @@next_block
  261.    pop ds
  262.    jmp @@readgood
  263. @@end_read:
  264.    pop cx
  265.    pop ds
  266. @@readgood:
  267.  
  268.    {-----------------------}
  269.  
  270.    { ahora posiciona el puntero del fichero al inicio de la tabla de }
  271.    { reubicación del fichero .EXE                                    }
  272.  
  273.    mov si,OFFSET header
  274.    mov ax,[si+18h]      { offset en bytes en el fichero de la tabla de }
  275.    mov dx,ax            { reubicación del .exe                         }
  276.    xor cx,cx
  277.    add dx,word ptr [pos]        { más la posición }
  278.    adc cx,word ptr [pos+2]
  279.    mov bx,[handle]
  280.    mov ah,42h
  281.    xor al,al
  282.    int 21h
  283.  
  284.    {------------------------}
  285.  
  286.    { ahora comienza la reubicación de verdad del fichero }
  287.  
  288.    mov si,OFFSET header
  289.    mov cx,[si+06h]      { número de datos de items de la tabla de reubicación }
  290.    test cx,0ffffh
  291.    jz @@no_realocate
  292. @@siguiente_item:
  293.    push cx
  294.    mov dx,OFFSET item
  295.    mov bx,[handle]
  296.    mov cx,4             { cada item se compone de offset:segmento -> 4 bytes }
  297.    mov ah,3fh
  298.    int 21h
  299.    mov bx,OFFSET item
  300.    mov ax,[StartSegment]        { a cada posición indicada por el item se  }
  301.    add ax,[bx+2]                { le suma el segmento de inicio del modulo }
  302.    mov di,[bx]
  303.    mov es,ax
  304.    mov ax,es:[di]
  305.    add ax,[StartSegment]
  306.    mov es:[di],ax
  307.    pop cx
  308.    loop @@siguiente_item
  309. @@no_realocate:
  310.  
  311.    {-------------------------}
  312.  
  313.    mov bx,[handle]
  314.    mov ah,3eh
  315.    int 21h                      { cierra el fichero }
  316.  
  317.    { set new PSP address...UNDOCUMENTED! }
  318.  
  319.    mov bx,[PSPSegment]
  320.    mov ah,50h
  321.    int 21h
  322.  
  323.    {-------------------------}
  324.  
  325.    { ahora le pasa la línea de comandos }
  326.  
  327.    push es
  328.    mov es,[PSPSegment]
  329.    mov di,080h
  330.    mov bx,OFFSET commandline
  331.    mov cl,[bx]
  332.    xor ch,ch
  333.    mov es:[di],cl
  334.    inc bx
  335.    inc di
  336.    test cx,0ffffh
  337.    jz @@ignora_com
  338. @@next_com:
  339.    mov al,[bx]
  340.    mov es:[di],al
  341.    inc bx
  342.    inc di
  343.    loop @@next_com
  344. @@ignora_com:
  345.    mov byte ptr es:[di],0dh
  346.    mov byte ptr es:[di+1],0
  347.    pop es
  348.  
  349.    {-------------------------}
  350.  
  351.    mov bx,OFFSET @@oldss
  352.  
  353.    cli
  354.    mov cs:[bx],ss
  355.    mov cs:[bx+2],sp
  356.    mov cs:[bx+4],bp
  357.    sti
  358.  
  359.    mov bx,OFFSET header
  360.    mov ax,[bx+0eh]
  361.    add ax,[StartSegment]
  362.  
  363.    cli
  364.    mov ss,ax
  365.    mov sp,[bx+10h]              { genera SS:SP a partir del header }
  366.    sti
  367.  
  368.    mov ax,[bx+14h]
  369.    mov dx,[bx+16h]
  370.    add dx,[StartSegment]        { DX:AX -> CS:IP }
  371.    push dx
  372.    push ax
  373.  
  374.    mov es,[PSPSegment]
  375.    mov ds,[PSPSegment]
  376.  
  377.    xor ax,ax                    { borra todos los registros }
  378.    mov di,ax
  379.    mov si,ax
  380.    mov bx,ax
  381.    mov cx,ax
  382.    mov dx,ax
  383.    mov bp,ax
  384.  
  385.    retf
  386. @@retorna:
  387.    mov bx,OFFSET @@oldss
  388.    cli
  389.    mov ss,cs:[bx]               { recupera todos los registros }
  390.    mov sp,cs:[bx+2]
  391.    mov bp,cs:[bx+4]
  392.    sti
  393.    mov ax,SEG @data
  394.    mov ds,ax
  395.  
  396.    {-----------------------}
  397.  
  398.    mov es,[PSPSegment]
  399.    mov ah,49h
  400.    int 21h                          { libera la memoria guardada por el }
  401.  
  402.    {-----------------------}
  403.  
  404.    jmp @@restore
  405.  
  406. @@oldss: dw 0
  407. @@oldsp: dw 0
  408. @@oldbp: dw 0
  409.  
  410. @@NoHayMem:
  411.        mov bx,[handle]
  412.        mov ah,3eh
  413.        int 21h                      { cierra el fichero }
  414. @@restore:
  415.           pop es
  416. END;
  417.  
  418. BEGIN
  419.  
  420.   LF_Coll.Init(10, 10);
  421.  
  422.   LF_Init('pump.exe', LF_Coll);
  423.   {LF_Init(ParamStr(0), LF_Coll);}
  424.  
  425. END.
  426.